﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer;
using Microsoft.SqlServer.Server;


public partial class Levenshtein
{
    [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true, Name = "fn_levenshtein", SystemDataAccess = SystemDataAccessKind.None)]
    public static SqlInt64 EditDistance(SqlString inSrc, SqlString inTrg, SqlBoolean ignoreCase)  
	{    
		string strSrc = ignoreCase ? inSrc.Value.ToLower() : inSrc.Value;    
		string strTrg = ignoreCase ? inTrg.Value.ToLower() : inTrg.Value;    
		int lenSrc = strSrc.Length;    
		int lenTrg = strTrg.Length;    
		int[,] matrix = new int[lenSrc + 1, lenTrg + 1];
        int cost = 0;

		for (int s = 0; s <= lenSrc; s++)      
        {
            matrix[s, 0] = s;
        } //for (int s = 0; s <= lenSrc; s++)   

		for (int t = 0; t <= lenTrg; t++)
        {
            matrix[0, t] = t;
        } //for (int t = 0; t <= lenTrg; t++)    

        for (int t = 1; t <= lenTrg; t++)    
		{      
		    for (int s = 1; s <= lenSrc; s++)      
			{
                cost = (strSrc.Substring(s - 1) == strTrg.Substring(t - 1) ? 0 : 1);

			    if (strSrc[s - 1] == strTrg[t - 1])          
				    matrix[s, t] = matrix[s - 1, t - 1];        
				else          
					matrix[s, t] = Math.Min(Math.Min(matrix[s - 1, t] + 1   // a deletion            
									                ,matrix[s, t - 1] + 1)  //an Insertion            
									       ,matrix[s - 1, t - 1] + cost);   // a substitution      
                                                              
		    }//for (int s = 1; s <= lenSrc; s++)    
		} //for (int t = 1; t <= lenTrg; t++)               
        
        return new SqlInt64(matrix[lenSrc, lenTrg]);  
	}
};

